import path from 'path'
import fs from 'fs'
import log4js from 'koa-log4'

// Resolve absolute log directory so logs can be written regardless of how the app is started (node, exe, or via Electron)
function resolveLogDir(): string {
  const execDir = path.dirname(process.execPath);
  const candidates = [
    path.join(execDir, 'back-end', 'logs'),
    path.resolve(process.cwd(), 'back-end', 'logs'),
    path.resolve(__dirname, '../../back-end/logs'),
  ];
  for (const dir of candidates) {
    try {
      if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
      return dir;
    } catch (e) {
      // try next candidate
    }
  }
  // Fallback to a local logs directory next to the executable
  const fallback = path.join(execDir, 'logs');
  if (!fs.existsSync(fallback)) fs.mkdirSync(fallback, { recursive: true });
  return fallback;
}

const LOG_DIR = resolveLogDir();
const DB_LOG_DIR = path.join(LOG_DIR, 'db');
if (!fs.existsSync(DB_LOG_DIR)) fs.mkdirSync(DB_LOG_DIR, { recursive: true });


log4js.configure({
  appenders: {
   access: {
    type: 'dateFile',
    pattern: '-yyyy-MM-dd.log', //生成文件的规则
    filename: path.join(LOG_DIR, 'access.log'), //生成文件名（绝对路径）
    alwaysIncludePattern: true,
    keepFileExt: true,
    daysToKeep: 7
   },
   application: {
    type: 'dateFile',
    pattern: '-yyyy-MM-dd.log',
    filename: path.join(LOG_DIR, 'application.log'),
    alwaysIncludePattern: true,
    keepFileExt: true,
    daysToKeep: 7
   },
  out: {
   type: 'console'
  },
      database: {
          type: "dateFile",
          pattern: "-yyyy-MM-dd.log",
          filename: path.join(DB_LOG_DIR,'db.log'),
          alwaysIncludePattern: true,
          keepFileExt: true,
          daysToKeep: 7
      }
  },
  categories: {
   default: { appenders: [ 'out' ], level: 'info' },
   access: { appenders: [ 'access' ], level: 'info' },
   // 同时输出到文件和终端
   application: { appenders: [ 'application', 'out' ], level: 'info'},
      db: {appenders:['database'],level:"info"}
  }
});

export const accessLogger = () => log4js.koaLogger(log4js.getLogger('access')); //记录所有访问级别的日志
export const logger = log4js.getLogger('application'); //记录所有应用级别的日志
export const httpLogger = log4js.getLogger("access") // 记录网络请求
export const dbLogger = log4js.getLogger("db")
// 将 console 方法绑定到文件日志，避免 Electron 启动 exe 时 stdout 未被消费导致阻塞
export function bindConsoleToLogger() {
  const appLogger = log4js.getLogger('application');
  const access = log4js.getLogger('access');
  const original = {
    log: console.log,
    info: console.info,
    warn: console.warn,
    error: console.error,
  };
  console.log = (...args: any[]) => appLogger.info(args.map(String).join(' '));
  console.info = (...args: any[]) => appLogger.info(args.map(String).join(' '));
  console.warn = (...args: any[]) => appLogger.warn(args.map(String).join(' '));
  console.error = (...args: any[]) => appLogger.error(args.map(String).join(' '));
  // 提供一个恢复方法（如有需要）
  return () => {
    console.log = original.log;
    console.info = original.info;
    console.warn = original.warn;
    console.error = original.error;
  };
}
export const formatText = {
    info: function(info) {
        var logText = new String();
        //响应日志头信息
        logText += "\n" + "***************info log start ***************" + "\n";
        //响应内容
        logText += "info detail: " + "\n" + JSON.stringify(info) + "\n";
        //响应日志结束信息
        logText += "*************** info log end ***************" + "\n";
        return logText;
    },
    request: function(req, resTime) {
        var logText = new String();
        var method = req.method;
        //访问方法
        logText += "request method: " + method + "\n";
        //请求原始地址
        logText += "request originalUrl:  " + req.originalUrl + "\n";
        //客户端ip
        logText += "request client ip:  " + req.ip + "\n";
        //开始时间
        var startTime;
        //请求参数
        if (method === 'GET') {
            logText += "request query:  " + JSON.stringify(req.query) + "\n";
            // startTime = req.query.requestStartTime;
        } else {
            logText += "request body: " + "\n" + JSON.stringify(req.body) + "\n";
            // startTime = req.body.requestStartTime;
        }
        //服务器响应时间
        logText += "response time: " + resTime + "\n";
        return logText;
    },
    response: function(ctx, resTime) {
        var logText = new String();
        //响应日志开始
        logText += "\n" + "*************** response log start ***************" + "\n";
        //添加请求日志
        logText += formatText.request(ctx.request, resTime) as string;
        //响应状态码
        logText += "response status: " + ctx.status + "\n";
        //响应内容
        logText += "response body: " + "\n" + JSON.stringify(ctx.body) + "\n";
        //响应日志结束
        logText += "*************** response log end ***************" + "\n";
        return logText;
    },
    handle: function(info) {
        var logText = new String();
        //响应日志开始
        logText += "\n" + "***************info log start ***************" + "\n";
        //响应内容
        logText += "handle info detail: " + "\n" + JSON.stringify(info).replace(/\\n/g, "\n") + "\n";
        //响应日志结束
        logText += "*************** info log end ***************" + "\n";
        return logText;
    },
    error: function(ctx, err, resTime) {
        var logText = new String();
        //错误信息开始
        logText += "\n" + "*************** error log start ***************" + "\n";
        //添加请求日志
        logText += formatText.request(ctx.request, resTime) as string;
        //错误名称
        logText += "err name: " + err.name + "\n";
        //错误信息
        logText += "err message: " + err.message + "\n";
        //错误详情
        logText += "err stack: " + err.stack + "\n";
        //错误信息结束
        logText += "*************** error log end ***************" + "\n";
        return logText;
    }
}
